﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace Treely.Data.Model.Abstract
{
    public interface IAnswerable
    {
        bool? Correct { get; set; }

        [Key]
        int QuestionId { get; set; }

        int PointValue { get; set; }

        string Title { get; set; }

        string Body { get; }

        QuestionSubject Subject { get; set; }

        AnswerType AnswerType { get; set; }

        int CorrectAnswer { get; set; }

        List<string> Answers { get; set; }

        DateTime Created { get; set; }

        string CreatedById { get; set; }

        ApplicationUser CreatedBy { get; set; }

        DateTime? Modified { get; set; }

        string ModifiedById { get; set; }

        ApplicationUser ModifiedBy { get; set; }

        DateTime? DeletionDate { get; set; }

        bool Deleted { get; set; }

        string DeletedById { get; set; }

        ApplicationUser DeletedBy { get; set; }

        bool IsCorrect(int answer);

        bool? IsCorrect(string answer);

        string ToStringVertical();

        DateTime? Started { get; set; }

        DateTime? Finished { get; set; }

        TimeSpan? TimeUsed { get; }
    }

    public class MathAnswerable : AuditObject, IAnswerable
    {
        [ForeignKey("MathQuiz")]
        public int MathQuizId { get; set; }

        public DateTime? Started { get; set; }

        public DateTime? Finished { get; set; }

        [Key]
        public int QuestionId { get; set; }

        public int PointValue { get; set; }

        public string Title { get; set; }

        public bool? Correct { get; set; }

        public TimeSpan? TimeUsed
        {
            get
            {
                if (Started == null || Finished == null)
                    return null;
                return (Finished - Started);
            }
        }

        protected Random RandomNumber { get; set; }

        public string Body
        {
            get
            {
                return (AnswerType == AnswerType.MultipleChoice)
            ? "Is the answer " + NumericAnswers.Select(x => x.ToString()).Aggregate((x, y) => x + " OR " + y) + "?"
            : "Enter the answer.";
            }
        }

        public QuestionSubject Subject { get; set; }

        public AnswerType AnswerType { get; set; }

        public int CorrectAnswer { get; set; }

        public List<string> Answers
        {
            get
            {
                return NumericAnswers.Select(x => x.ToString()).ToList();
            }
            set { NumericAnswers = value.Select(int.Parse).ToList(); }
        }

        public List<int> NumericAnswers { get; set; }

        public bool IsCorrect(int answer)
        {
            return (answer == CorrectAnswer);
        }

        public bool? IsCorrect(string answer)
        {
            int intAnswer;
            if (Int32.TryParse(answer, out intAnswer))
                return IsCorrect(intAnswer);
            return null;
        }

        public virtual string ToStringVertical()
        {
            return string.Empty;
        }

        public virtual string ToStringVertical(char mathOperator, List<int> list)
        {
            var sb = new StringBuilder();
            var maxLength = list.Max().ToString().Length;
            for (var i = 0; i < list.Count; i++)
            {
                if (i == (list.Count - 1))
                {
                    sb.Append(string.Format("{0}", mathOperator));
                    AlignDigits(maxLength, list[i], sb);
                    sb.Append(list[i]);
                    sb.AppendLine();
                    Enumerable.Repeat("_", maxLength + 1).ToList().ForEach(x => sb.Append(x));
                }
                else
                {
                    sb.Append(" ");
                    AlignDigits(maxLength, list[i], sb);
                    sb.AppendLine(list[i].ToString());
                }
            }
            return sb.ToString();
        }

        private void AlignDigits(int maxLength, int thisNumber, StringBuilder sb)
        {
            var spaces = maxLength - thisNumber.ToString().Length;
            for (var i = 0; i < spaces; i++)
            {
                sb.Append(" ");
            }
        }
    }

    public enum QuestionSubject
    {
        None,
        Addition,
        Subtraction,
        Multiplication,
        Division
    }

    public enum AnswerType
    {
        None,
        Text,
        MultipleChoice
    }
}